package errors

import (
	"fmt"
	"net/http"
)

// ErrorCode 错误码类型
type ErrorCode int

const (
	// 系统级错误码
	ErrInternalServer ErrorCode = iota + 10000
	ErrInvalidRequest
	ErrUnauthorized
	ErrForbidden
	ErrNotFound
	ErrMethodNotAllowed
	ErrRequestTimeout
	ErrTooManyRequests

	// 数据库错误码
	ErrDatabaseConnection ErrorCode = iota + 20000
	ErrDatabaseQuery
	ErrDatabaseTransaction
	ErrDatabaseDuplicate
	ErrDatabaseNotFound

	// 业务错误码
	ErrInvalidParameter ErrorCode = iota + 30000
	ErrResourceNotFound
	ErrResourceExists
	ErrResourceLocked
	ErrResourceExpired
	ErrOperationFailed
	ErrPermissionDenied
)

// Error 自定义错误类型
type Error struct {
	Code    ErrorCode `json:"code"`
	Message string    `json:"message"`
	Err     error     `json:"-"`
}

// Error 实现error接口
func (e *Error) Error() string {
	if e.Err != nil {
		return fmt.Sprintf("[%d] %s: %v", e.Code, e.Message, e.Err)
	}
	return fmt.Sprintf("[%d] %s", e.Code, e.Message)
}

// Unwrap 实现errors.Unwrap接口
func (e *Error) Unwrap() error {
	return e.Err
}

// New 创建新的错误
func New(code ErrorCode, message string) *Error {
	return &Error{
		Code:    code,
		Message: message,
	}
}

// Wrap 包装已有错误
func Wrap(code ErrorCode, message string, err error) *Error {
	return &Error{
		Code:    code,
		Message: message,
		Err:     err,
	}
}

// HTTPStatusCode 获取HTTP状态码
func (e *Error) HTTPStatusCode() int {
	switch e.Code {
	case ErrInvalidRequest:
		return http.StatusBadRequest
	case ErrUnauthorized:
		return http.StatusUnauthorized
	case ErrForbidden:
		return http.StatusForbidden
	case ErrNotFound:
		return http.StatusNotFound
	case ErrMethodNotAllowed:
		return http.StatusMethodNotAllowed
	case ErrRequestTimeout:
		return http.StatusRequestTimeout
	case ErrTooManyRequests:
		return http.StatusTooManyRequests
	default:
		return http.StatusInternalServerError
	}
}

// IsNotFound 判断是否为资源不存在错误
func IsNotFound(err error) bool {
	if e, ok := err.(*Error); ok {
		return e.Code == ErrNotFound || e.Code == ErrResourceNotFound
	}
	return false
}

// IsDuplicate 判断是否为资源重复错误
func IsDuplicate(err error) bool {
	if e, ok := err.(*Error); ok {
		return e.Code == ErrDatabaseDuplicate || e.Code == ErrResourceExists
	}
	return false
}

// IsPermissionDenied 判断是否为权限错误
func IsPermissionDenied(err error) bool {
	if e, ok := err.(*Error); ok {
		return e.Code == ErrForbidden || e.Code == ErrPermissionDenied
	}
	return false
}
